package sxe.core.math;

import snobject.snDouble;
import snobject.snInteger;
import snobject.snObject;
import snobject.snObjectArgList;
import step.FunctionWrapper;
import step.EvaluationFailure;

/**
 * Returns the absolute value of a value.
 * If the argument is not negative, the argument is returned.
 * If the argument is negative, the negation of the argument is returned.
 * @param argv must contain an snInteger or snDouble object at top of the stack 
 * @return returns the absolute value of the argument
 */

public class abs extends FunctionWrapper{
	public snObject Call(snObjectArgList argv) throws EvaluationFailure{
		// REQUIRES: argv must contain an snInteger or snDouble object at top of the stack
		// EFFECTS: returns the snObject of the absolute value of the value from argv
		boolean isDbl = false;
		double ret = 0;
		int index = argv.index();
		
		// If the next value of argv is a snDouble, set ret to be a double and isDble to be true 
		if(argv.popObject() instanceof snDouble){
			ret = ((snDouble)argv.objectAt(index)).getDouble();
			isDbl = true;
		}
		//otherwise, ret is an integer
		else
			ret = ((snInteger)argv.objectAt(index)).getInteger();
		
		//if ret is negative, make it positive
		if(ret < 0){
			ret = -ret;
		}
		
		//return the ret as an snDouble if ret is a double, otherwise return ret as an snInteger
		if(isDbl)
			return new snDouble(new Double(ret));
		else
			return new snInteger(new Integer((new Double (ret)).intValue()));
	}
}